package coupon

import (
	sqlc "bp/db/sqlc"
	"bp/internal/util"
	"context"
	"fmt"
	"time"
)

func (s *CouponEntityServiceImp) AsyncCallHandleFail(ctx context.Context, err *error) {
	var errMsg string
	if r := recover(); r != nil {
		errMsg = fmt.Sprintf("AsyncCallHandleFail recover panic:%s", r)
	} else if err != nil && (*err) != nil {
		errMsg = fmt.Sprintf("AsyncCallHandleFail normal err:%s", (*err).Error())
	}
	if errMsg != "" {
		s.slog.Errorf("AsyncCallHandleFail err:%v", errMsg)
	}
}

// BatchCreateLessCouponDistributionDetail 批量新建券投放明细
func (s *CouponEntityServiceImp) batchCreateLessCouponDistributionDetail(ctx context.Context, ptr *AsyncBatchCreateCouponDistributionDetailParam, execSeq, size int) (err error) {
	var count int = 0
	sqlParam := sqlc.UpsertCouponDistributionDetailParams{
		DistributionID: ptr.CouponDistributionPtr.ID,
		CouponID:       ptr.CouponDistributionPtr.CouponID,
	}
	start := time.Now().Unix()
	err = s.dao.NewTxRunner().SqlcExecTx(ctx, func(q *sqlc.Queries) (err error) {
		for count = 0; count < size; count++ {
			sqlParam.Sn = ptr.CouponDistributionPtr.BatchNo + util.RandomStringEx(20)
			fmt.Printf("execSeq(%d)sn=>%s\n", execSeq, sqlParam.Sn)
			err = q.UpsertCouponDistributionDetail(ctx, sqlParam)
			if err != nil {
				return
			}
		}
		return
	})
	if err != nil {
		return
	}
	end := time.Now().Unix()
	s.slog.Infof("1 AsyncBatchCreateCouponDistributionDetail 批量新建券投放明细批次号(%s)-(%d) 新建(%d)条 耗时(%d) ok", ptr.CouponDistributionPtr.BatchNo, execSeq, count, (end - start))
	return
}

// AsyncBatchCreateCouponDistributionDetailParam 批量新建少量	券投放明细
type AsyncBatchCreateCouponDistributionDetailParam struct {
	CouponDistributionPtr *sqlc.CouponDistribution
}

// AsyncBatchCreateLessCouponDistributionDetail 批量新建少量	券投放明细
func (s *CouponEntityServiceImp) AsyncBatchCreateCouponDistributionDetail(ctxRaw context.Context, ptr *AsyncBatchCreateCouponDistributionDetailParam) {
	segSize := 1000
	var err error
	ctx := context.Background()
	defer s.AsyncCallHandleFail(ctx, &err)
	start := time.Now().Unix()
	util.SegmentExec(func(execSeq, size int, done util.SegmentDone) {
		err = s.batchCreateLessCouponDistributionDetail(ctx, ptr, execSeq, size)
		done()
	}, func() {
		ctx := context.Background()
		err = s.dao.NewTxRunner().SqlcExecTx(ctx, func(q *sqlc.Queries) (err error) {
			distributionID := ptr.CouponDistributionPtr.ID
			err = q.MarkCouponDistributionExecuted(ctx, distributionID)
			if err != nil {
				return
			}
			s.slog.Infof("MarkCouponDistributionExecuted ok")
			couponID := ptr.CouponDistributionPtr.CouponID
			err = q.BackFillCouponROIssuers(ctx, couponID)
			if err != nil {
				return
			}
			s.slog.Infof("BackFillCouponROIssuers ok")
			err = q.UpdateCouponDistributionStatDistributedCnt(ctx, distributionID)
			if err != nil {
				return
			}
			s.slog.Infof("UpdateCouponDistributionStatDistributedCnt ok")
			err = q.UpdateCouponStatDistributedCnt(ctx, couponID)
			if err != nil {
				return
			}
			s.slog.Infof("UpdateCouponStatDistributedCnt ok")
			return
		})
		if err != nil {
			s.slog.Infof("1 AsyncBatchCreateCouponDistributionDetai err:%s", err.Error())
		} else {
			end := time.Now().Unix()
			s.slog.Infof("1 AsyncBatchCreateCouponDistributionDetail 批量新建券投放明细(%d)条 批次号(%s) 总耗时(%d) ok", ptr.CouponDistributionPtr.Cnt, ptr.CouponDistributionPtr.BatchNo, (end - start))
		}
	}, int(ptr.CouponDistributionPtr.Cnt), segSize)
}

// GetCouponSnAvailableParam 获取可用的sn参数
type GetCouponSnAvailableParam struct {
	CouponID        int64
	Issuer          string
	DistributeScene string
	MemberID        int64
}

// 获取可用的sn
func (s *CouponEntityServiceImp) GetAndUpdateCouponSnAvailable(ctx context.Context, q *sqlc.Queries, ptr *GetCouponSnAvailableParam) (
	sn string,
	distributionID int64,
	err error) {
	slog := util.NewContextLogger(ctx, s.slog)
	couponDistributionDetail, err := q.MarkCouponSnGot(ctx, sqlc.MarkCouponSnGotParams{
		RecipientID:     sqlc.NInt64FromInt64(ptr.MemberID),
		CouponID:        ptr.CouponID,
		Issuer:          ptr.Issuer,
		DistributeScene: ptr.DistributeScene,
	})
	if err != nil {
		return
	}
	sn = couponDistributionDetail.Sn
	distributionID = couponDistributionDetail.DistributionID
	slog.Infof("GetCouponSnAvailable sn=>%s, distributionID=>%d", sn, distributionID)
	return
}
